{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Solutions to Question 5 in the Diagnostic Quiz for\n",
    "# \"The Mathematical Engineering of Deep Learning\"\n",
    "\n",
    "See [deeplearningmath.org](https://deeplearningmath.org)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5a: Given an input matrix, check if it is: Symmetric, upper-triangular, lower-triangular."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "checkMatrix"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"\"\"\n",
    "Check if an input matrix is:\n",
    "* Symmetric\n",
    "* Upper-triangular\n",
    "* Lower-traingular\n",
    "\n",
    "Returns an array of symbols including `:notSquare`,\n",
    "`:symmetric`, `:lowerTriangular`, `:upperTriangular`\n",
    "\n",
    "\"\"\"\n",
    "function checkMatrix(matrix::Array{T,2}) where T<:Number\n",
    "    n, m = size(matrix)\n",
    "    n != m && return [:notSquare]\n",
    "    \n",
    "    symmetricFlag, lowerTriangularFlag, upperTriangularFlag = true, true, true\n",
    "    \n",
    "    for i in 2:n\n",
    "        for j in 2:i-1\n",
    "            symmetricFlag &= matrix[i,j] == matrix[j,i]\n",
    "            lowerTriangularFlag &= matrix[i,j] == 0\n",
    "            upperTriangularFlag &= matrix[j,i] == 0\n",
    "        end\n",
    "    end\n",
    "    \n",
    "    descriptors = []\n",
    "    symmetricFlag && push!(descriptors,:symmetric) \n",
    "    lowerTriangularFlag && push!(descriptors,:lowerTriangular) \n",
    "    upperTriangularFlag && push!(descriptors,:upperTriangular) \n",
    "    return descriptors \n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "search: \u001b[0m\u001b[1mc\u001b[22m\u001b[0m\u001b[1mh\u001b[22m\u001b[0m\u001b[1me\u001b[22m\u001b[0m\u001b[1mc\u001b[22m\u001b[0m\u001b[1mk\u001b[22m\u001b[0m\u001b[1mM\u001b[22m\u001b[0m\u001b[1ma\u001b[22m\u001b[0m\u001b[1mt\u001b[22m\u001b[0m\u001b[1mr\u001b[22m\u001b[0m\u001b[1mi\u001b[22m\u001b[0m\u001b[1mx\u001b[22m\n",
      "\n"
     ]
    },
    {
     "data": {
      "text/latex": [
       "Check if an input matrix is:\n",
       "\n",
       "\\begin{itemize}\n",
       "\\item Symmetric\n",
       "\n",
       "\n",
       "\\item Upper-triangular\n",
       "\n",
       "\n",
       "\\item Lower-traingular\n",
       "\n",
       "\\end{itemize}\n",
       "Returns an array of symbols including \\texttt{:notSquare}, \\texttt{:symmetric}, \\texttt{:lowerTriangular}, \\texttt{:upperTriangular}\n",
       "\n"
      ],
      "text/markdown": [
       "Check if an input matrix is:\n",
       "\n",
       "  * Symmetric\n",
       "  * Upper-triangular\n",
       "  * Lower-traingular\n",
       "\n",
       "Returns an array of symbols including `:notSquare`, `:symmetric`, `:lowerTriangular`, `:upperTriangular`\n"
      ],
      "text/plain": [
       "  Check if an input matrix is:\n",
       "\n",
       "    •    Symmetric\n",
       "\n",
       "    •    Upper-triangular\n",
       "\n",
       "    •    Lower-traingular\n",
       "\n",
       "  Returns an array of symbols including \u001b[36m:notSquare\u001b[39m, \u001b[36m:symmetric\u001b[39m,\n",
       "  \u001b[36m:lowerTriangular\u001b[39m, \u001b[36m:upperTriangular\u001b[39m"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "? checkMatrix"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0-element Array{Any,1}"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "using Random\n",
    "Random.seed!(0)\n",
    "A = rand(1:5,4,4)\n",
    "checkMatrix(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1-element Array{Symbol,1}:\n",
       " :notSquare"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Random.seed!(0)\n",
    "A = rand(1:5,4,5)\n",
    "checkMatrix(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1-element Array{Any,1}:\n",
       " :symmetric"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Random.seed!(0)\n",
    "A = rand(1:5,4,4)\n",
    "A = (A' + A)/2\n",
    "checkMatrix(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1-element Array{Any,1}:\n",
       " :lowerTriangular"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Random.seed!(0)\n",
    "A = rand(1:5,4,4)\n",
    "for i in 2:4\n",
    "    for j in 2:4-1\n",
    "        A[i,j] = 0\n",
    "    end\n",
    "end\n",
    "checkMatrix(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1-element Array{Any,1}:\n",
       " :upperTriangular"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Random.seed!(0)\n",
    "A = rand(1:5,4,4)\n",
    "for i in 2:4\n",
    "    for j in 2:4-1\n",
    "        A[j,i] = 0\n",
    "    end\n",
    "end\n",
    "checkMatrix(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3-element Array{Any,1}:\n",
       " :symmetric\n",
       " :lowerTriangular\n",
       " :upperTriangular"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "using LinearAlgebra\n",
    "Random.seed!(0)\n",
    "A = diagm(rand(1:5,4))\n",
    "checkMatrix(A)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5b) Given a list of numbers, return a sorted list of numbers."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "bubbleSort!"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"\"\"\n",
    "Sorts the input array according to the bubble sort algorithm. Sorts in place.\n",
    "This is taken from [\"Statistics with Julia\"](https://statisticswithjulia.org/), Listing 1.6.\n",
    "\"\"\"\n",
    "function bubbleSort!(a::Array{T}) where T\n",
    "    n = length(a)\n",
    "    for i in 1:n-1\n",
    "        for j in 1:n-i\n",
    "            if a[j] > a[j+1]\n",
    "                a[j], a[j+1] = a[j+1], a[j]\n",
    "            end\n",
    "        end\n",
    "    end\n",
    "    return a\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "search: \u001b[0m\u001b[1mb\u001b[22m\u001b[0m\u001b[1mu\u001b[22m\u001b[0m\u001b[1mb\u001b[22m\u001b[0m\u001b[1mb\u001b[22m\u001b[0m\u001b[1ml\u001b[22m\u001b[0m\u001b[1me\u001b[22m\u001b[0m\u001b[1mS\u001b[22m\u001b[0m\u001b[1mo\u001b[22m\u001b[0m\u001b[1mr\u001b[22m\u001b[0m\u001b[1mt\u001b[22m\u001b[0m\u001b[1m!\u001b[22m\n",
      "\n"
     ]
    },
    {
     "data": {
      "text/latex": [
       "Sorts the input array according to the bubble sort algorithm. Sorts in place. This is taken from \\href{https://statisticswithjulia.org/}{\"Statistics with Julia\"}, Listing 1.6.\n",
       "\n"
      ],
      "text/markdown": [
       "Sorts the input array according to the bubble sort algorithm. Sorts in place. This is taken from [\"Statistics with Julia\"](https://statisticswithjulia.org/), Listing 1.6.\n"
      ],
      "text/plain": [
       "  Sorts the input array according to the bubble sort algorithm. Sorts in\n",
       "  place. This is taken from \"Statistics with Julia\"\n",
       "  (https://statisticswithjulia.org/), Listing 1.6."
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "? bubbleSort!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10-element Array{Int64,1}:\n",
       "  1\n",
       " 19\n",
       " 17\n",
       " 11\n",
       "  1\n",
       " 20\n",
       " 15\n",
       " 12\n",
       "  6\n",
       "  8"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "using Random\n",
    "Random.seed!(0)\n",
    "data = rand(1:20,10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10-element Array{Int64,1}:\n",
       "  1\n",
       "  1\n",
       "  6\n",
       "  8\n",
       " 11\n",
       " 12\n",
       " 15\n",
       " 17\n",
       " 19\n",
       " 20"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bubbleSort!(data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5c) Given a sequence of $n$ input vectors, each of length $p$, compute the $p\\times p$ sample covariance matrix of these vectors.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "myCov"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"\"\"\n",
    "\n",
    "See also [\"Statistics with Julia\"](https://statisticswithjulia.org/), Listing 4.13.\n",
    "\"\"\"\n",
    "function myCov(dataArray::Array{Array{T,1},1}) where T <: Number\n",
    "    n = length(dataArray)\n",
    "    p = length(dataArray[1])\n",
    "    sums = zeros(p)\n",
    "    for x in dataArray\n",
    "        sums += x\n",
    "    end\n",
    "    demeanedData = [x - sums/n for x in dataArray]\n",
    "    cov = zeros(T,p,p)\n",
    "    for x in demeanedData\n",
    "        cov += x*x'\n",
    "    end\n",
    "    return cov/(n-1)\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "search: \u001b[0m\u001b[1mm\u001b[22m\u001b[0m\u001b[1my\u001b[22m\u001b[0m\u001b[1mC\u001b[22m\u001b[0m\u001b[1mo\u001b[22m\u001b[0m\u001b[1mv\u001b[22m\n",
      "\n"
     ]
    },
    {
     "data": {
      "text/latex": [
       "See also \\href{https://statisticswithjulia.org/}{\"Statistics with Julia\"}, Listing 4.13.\n",
       "\n",
       "\\rule{\\textwidth}{1pt}\n",
       "See also \\href{https://statisticswithjulia.org/}{\"Statistics with Julia\"}, Listing 4.13.\n",
       "\n"
      ],
      "text/markdown": [
       "See also [\"Statistics with Julia\"](https://statisticswithjulia.org/), Listing 4.13.\n",
       "\n",
       "---\n",
       "\n",
       "See also [\"Statistics with Julia\"](https://statisticswithjulia.org/), Listing 4.13.\n"
      ],
      "text/plain": [
       "  See also \"Statistics with Julia\" (https://statisticswithjulia.org/), Listing\n",
       "  4.13.\n",
       "\n",
       "  ────────────────────────────────────────────────────────────────────────────\n",
       "\n",
       "  See also \"Statistics with Julia\" (https://statisticswithjulia.org/), Listing\n",
       "  4.13."
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "? myCov"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "isposdef(Σ) = true\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "3×3 Array{Float64,2}:\n",
       " 2.00118   0.303433  0.699163\n",
       " 0.303433  4.00789   1.50352\n",
       " 0.699163  1.50352   2.29857"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "using Random, Distributions, LinearAlgebra\n",
    "Random.seed!(0)\n",
    "μ = [10, 20, 30] #To enter a symbol like μ use \\mu + [TAB]\n",
    "Σ = [2 0.3 0.7;\n",
    "     0.3 4 1.5;\n",
    "     0.7 1.5 2.3]  #To enter a symbol like Σ use \\Sigma + [TAB]\n",
    "@show isposdef(Σ)\n",
    "dist = MvNormal(μ,Σ)\n",
    "N = 10^6\n",
    "data = [rand(dist) for _ in 1:N]\n",
    "myCov(data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5d) Use brute-force Riemann sums to illustrate numerically that \n",
    "\n",
    "$$\n",
    "\\int_{x_1 = -5}^5 \\int_{x_2= -5}^5 ~\\frac{1}{2 \\pi}e^{-\\frac{x_1^2 + x_2^2}{2}} ~ dx_1\\, dx_2  \\approx 1.\n",
    "$$\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.9999988828806374"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "δ = 0.01\n",
    "sum([1/2π * exp(-(x₁^2 + x₂^2)/2) * δ^2 for x₁ in -5:δ:5, x₂ in -5:δ:5])"
   ]
  }
 ],
 "metadata": {
  "@webio": {
   "lastCommId": null,
   "lastKernelId": null
  },
  "kernelspec": {
   "display_name": "JuliaPro_v1.4.2-1 1.4.2",
   "language": "julia",
   "name": "juliapro_v1.4.2-1-1.4"
  },
  "language_info": {
   "file_extension": ".jl",
   "mimetype": "application/julia",
   "name": "julia",
   "version": "1.4.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
